package wrap

import (
	"net/http"
	"log"
	"os"
)

//被包装的handler的类型
type Handler func(writer http.ResponseWriter, request *http.Request) error

//用户error 如果是用户error就直接返回去 否则走系统错误
type UserError interface {
	error
	Message() string
}

//闭包包装函数
func ErrWrapper(handler Handler) func(writer http.ResponseWriter, request *http.Request) {

	//返回原始的函数类型
	return func(writer http.ResponseWriter, request *http.Request) {
		//防止运行时出现的panic
		defer func() {
			if err := recover(); err != nil {
				log.Println(err)
				//统一处理非预料的错误
				http.Error(writer,
					http.StatusText(http.StatusInternalServerError),
					http.StatusInternalServerError)
			}
		}()

		//处理正常业务错误
		err := handler(writer, request)
		if err != nil {
			log.Println(err)
			if userError, ok := err.(UserError); ok {
				//判定是用户错误 直接返回给前端
				http.Error(writer, userError.Message(), http.StatusBadRequest)
			}
		}
		//处理handler抛出来的系统异常
		code := http.StatusOK
		switch {
		case os.IsNotExist(err):
			code = http.StatusNotFound
		case os.IsPermission(err):
			code = http.StatusForbidden
		default:
			code = http.StatusInternalServerError
		}
		http.Error(writer, string(code), http.StatusBadRequest)
	}
}
